package main

import (
	"bufio"
	"github.com/urfave/cli/v2"
	"log"
	"os"
	"os/exec"
	"strconv"
	"strings"
)

type deviceInfo struct {
	DeviceIP       string
	DeviceBatLevel int
	NeedRepair     bool
}

func getDeviceIp(infile string) []string {
	deviceIpList := make([]string, 0)
	f, err := os.Open(infile)
	if err != nil {
		log.Printf("open %s failed.\n", infile)
		return deviceIpList
	}
	defer f.Close()
	input := bufio.NewScanner(f)
	for input.Scan() {
		deviceIpList = append(deviceIpList, input.Text())
	}
	return deviceIpList
}

func getDeviceBatLevel(host string) deviceInfo {
	cmd := exec.Command("getpower", host)
	ret, err := cmd.Output()
	if err != nil {
		log.Printf("run command failed.\n")
	}
	if string(ret) == "" {
		ret = []byte("level:100")
	}
	batInfoSlice := strings.Split(strings.TrimSpace(string(ret)), ":")
	var batLevelValue int
	var devInfo deviceInfo
	batLevelValue, err = strconv.Atoi(strings.TrimSpace(batInfoSlice[len(batInfoSlice)-1]))
	if err != nil {
		log.Printf("convert string to int type failed.\n")
	} else {
		devInfo.NeedRepair = false
		if batLevelValue < 20 {
			devInfo.NeedRepair = true
		}
	}
	devInfo.DeviceIP = host
	devInfo.DeviceBatLevel = batLevelValue
	return devInfo
}

func createOutputFile(outfile string) (*os.File, error) {
	return os.Create(outfile)
}

func recordDetectResult(info deviceInfo, f *os.File) {
	if info.NeedRepair {
		f.WriteString(info.DeviceIP + "\n")
	}
}

func main() {
	var inputFilePath, outputFilePath string
	app := &cli.App{
		Commands: []*cli.Command{
			{
				Name:    "get",
				Aliases: []string{"g"},
				Usage:   "get the phone battery level.",
				Action: func(c *cli.Context) error {
					deviceIp := getDeviceIp(inputFilePath)
					f, err := createOutputFile(outputFilePath)
					if err != nil {
						log.Printf("create outputfile %s failed\n", outputFilePath)
						return nil
					}
					defer f.Close()
					for i, ip := range deviceIp {
						info := getDeviceBatLevel(ip)
						recordDetectResult(info, f)
						log.Printf("Aready done: %d\n", i+1)
					}
					return nil
				},

				Flags: []cli.Flag{
					&cli.StringFlag{
						Name:        "inputFile",
						Aliases:     []string{"i"},
						Usage:       "input ip file to be queried.",
						Destination: &inputFilePath,
					},
					&cli.StringFlag{
						Name:        "outputFile",
						Aliases:     []string{"o"},
						Usage:       "output file saves the queried results.",
						Destination: &outputFilePath,
					},
				},
			},
		},
	}

	err := app.Run(os.Args)
	if err != nil {
		log.Fatal(err)
	}
}
